﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using RayDen.Library.Entity.Interface;

namespace RayDen.Library.Entity {
    [DataContract]
    public class ConfigurableEntity : IParameterBag, IDictionary<string, object> {

        [DataMember]
        protected Dictionary<string, object> items;

        public ConfigurableEntity() {
            items = new Dictionary<string, object>();
        }
        public ConfigurableEntity(ConfigurableEntity copy)
        {
            items = new Dictionary<string, object>(copy.items);
        }

        public void Add<TValue>(string name, TValue val) {
            items.Add(name, val);
        }

        #region IParameterBag Members

        public virtual TValue Get<TValue>(string name) {
            object result;

            return items.TryGetValue(name, out result) ? (TValue) result : default(TValue);
        }

        public virtual TValue Get<TValue>(string name, TValue @default) {
            object result;
            if (!items.TryGetValue(name, out result)) {
                return @default;
            }
            return (TValue)result;
        }

        public virtual void Set<TValue>(string name, TValue val) {
            if (items.ContainsKey(name)) {
                items[name] = val;
            }
            else {
                items.Add(name, val);
            }
        }

        public void Merge(IParameterBag bag) {
            items = items.Union(bag).ToDictionary(item => item.Key, item => item.Value);
        }

        public Dictionary<string, object> GetItems() {
            return this.items;
        }

        #endregion

        #region IEnumerable<KeyValuePair<string,object>> Members

        public IEnumerator<KeyValuePair<string, object>> GetEnumerator() {
            return items.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
            return items.GetEnumerator();
        }

        #endregion

        public void Add(KeyValuePair<string, object> item) {
            this.items.Add(item.Key, item.Value);
        }

        public void Clear() {
            this.items.Clear();
        }

        public bool Contains(KeyValuePair<string, object> item) {
            return this.items.ContainsKey(item.Key);
        }

        public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex) {
            Array.Copy(this.items.ToArray(), array, arrayIndex);
        }

        public bool Remove(KeyValuePair<string, object> item) {
            return this.items.Remove(item.Key);
        }

        public int Count {
            get { return items.Count; }
        }

        public bool IsReadOnly {
            get { return false; }
        }

        public bool ContainsKey(string key) {
            return this.items.ContainsKey(key);
        }

        public void Add(string key, object value) {
            this.items.Add(key, value);
        }

        public bool Remove(string key) {
            return this.items.Remove(key);
        }

        public bool TryGetValue(string key, out object value) {
            return items.TryGetValue(key, out value);
        }

        public object this[string key] {
            get { return items[key]; }
            set { items[key]=value; }
        }

        public ICollection<string> Keys {
            get { return items.Keys; }
        }

        public ICollection<object> Values {
            get { return items.Values; }
        }
    }
}
